#if _DEBUG

#include <cppunit/config/SourcePrefix.h>

#include "../source/Uses.h"
#include "TestUses.h"
#include <iterator>

//using namespace std;
//using namespace boost;
 //Uses u1;
 
void UsesTest::SetUp(void)
{}


void UsesTest::TearDown(void)
{
}

CPPUNIT_TEST_SUITE_REGISTRATION(UsesTest);



void UsesTest::TestConstructor() {

	u1.InitializeUses(32);
	int i = u1.num_of_statements;
	CPPUNIT_ASSERT(i==32);
}
/*
void UsesTest::TestInsertUses() {
//	cout << u1.num_of_statements;
	STMT s;
	s.statement_number = 1;
	u1.InsertUses(s,2,3);
	CPPUNIT_ASSERT(u1.uses_list.size() == 1);

}

void UsesTest::TestInsertDupUses() {
	STMT s;
	s.statement_number = 1;
	u1.InsertUses(s, 2, 3);
	CPPUNIT_ASSERT(u1.uses_list.size() == 1);
}

void UsesTest::TestInsertSecond() {
	STMT s;
	s.statement_number = 1;
	u1.InsertUses(s, 2, 4);
	CPPUNIT_ASSERT(u1.uses_list.size() == 2);
}

void UsesTest::TestClearMap() {
	u1.uses_list.clear();
	CPPUNIT_ASSERT(u1.uses_list.size() == 0);
}
*/
void UsesTest::TestInsertActualRelations() {

	// symbol table:
	// x = 0, y = 1, z = 2, i = 3

	// proc table:
	// 'Main' = 0, 'P' = 1
	
	STMT s1, s2, s3, s4, s5;
	s1.node_type = ASSIGN;
	s1.statement_number = 1;
	s2.node_type = WHILE;
	s2.statement_number = 2;
	s3.node_type = ASSIGN;
	s3.statement_number = 3;
	s4.node_type = CALL;
	s4.statement_number = 4;
	s5.node_type = ASSIGN;
	s5.statement_number = 5;

	//  x = x + y + z
	u1.InsertUses(s1, 0, 0); // 1
	u1.InsertUses(s1, 1, 0); // 2
	u1.InsertUses(s1, 2, 0); // 3

	//while i {y = x + .... }
	u1.InsertUses(s2, 3, 0); // 4
	u1.InsertUses(s2, 0, 0);
	u1.InsertUses(s2, 2, 0);

	// y = x + i * 2
	u1.InsertUses(s3, 0, 0);
	u1.InsertUses(s3, 3, 0);

	// call P;
	u1.InsertUses(s4, 0, 0);
	u1.InsertUses(s4, 2, 0);


	// x = x + z
	u1.InsertUses(s5, 0, 1); // 5
	u1.InsertUses(s5, 2, 1); // 6

	CPPUNIT_ASSERT(u1.stmt_vars.size() == 5);
	

}

void UsesTest::TestGetVariablesUsedByAssignment() {
	STMT s;

	s.node_type = ASSIGN;
	s.statement_number = 1;
	VARINDEX_ARRAY v_a1 = u1.GetVariablesUsedByAssignment(s);
	VARINDEX_ARRAY::iterator v_i = v_a1.find(0);
	CPPUNIT_ASSERT(v_i != v_a1.end());

	v_i = v_a1.find(1);
	CPPUNIT_ASSERT(v_i != v_a1.end());

	v_i = v_a1.find(2);
	CPPUNIT_ASSERT(v_i != v_a1.end());

	v_i = v_a1.find(3);
	CPPUNIT_ASSERT(v_i == v_a1.end());

	v_i = v_a1.find(-1);
	CPPUNIT_ASSERT(v_i == v_a1.end());


}



void UsesTest::TestGetContainerUsesVariable() {

	STMT parent1;
	parent1.node_type = WHILE;
	parent1.statement_number = 2;

	STMT child1;
	child1.node_type = ASSIGN;
	child1.statement_number = 3;

	STMT child2;
	child2.node_type = ASSIGN;
	child2.statement_number = 4;

	u1.parent_test.InsertParent(parent1, child1);
	u1.parent_test.InsertParent(parent1, child2);
	u1.proc_test.InsertProc("Main");
	u1.proc_test.InsertProc("P");

//	u1.p1.InsertParent(parent1, child1);
	STMT_ARRAY s_a1 = u1.GetContainerUsesVariable(2, WHILE);

	// test that statement 2 (while) uses x : true
	STMT s;
	s.node_type = WHILE;
	s.statement_number = 2;

	auto iter = s_a1.find(s);
	CPPUNIT_ASSERT(iter != s_a1.end());
	//CPPUNIT_ASSERT(1==1);
		

//	s.node_type = ;
//	s.statement_number = 
}

void UsesTest::TestGetAssignmentUses() {
	STMT a;
	a.node_type = ASSIGN;
	a.statement_number = 3;

	CPPUNIT_ASSERT(u1.GetAssignmentUses(a, 0));
	
}

void UsesTest::TestGetVariablesUsedByContainer() {
	STMT container;
	container.node_type = WHILE;
	container.statement_number = 2;
	VARINDEX_ARRAY v_a1 = u1.GetVariablesUsedByContainer(container);

	// assert that x is used
	auto i = v_a1.find(0);
	CPPUNIT_ASSERT(i != v_a1.end());

	// assert that y is unused
	i = v_a1.find(1);
	CPPUNIT_ASSERT(i == v_a1.end());

	// assert z is used
	i = v_a1.find(2);
	CPPUNIT_ASSERT(i != v_a1.end());

	// assert i is used
	i = v_a1.find(3);
	CPPUNIT_ASSERT(i != v_a1.end());

	// boundary test
	i = v_a1.find(4);
	CPPUNIT_ASSERT(i == v_a1.end());

	i = v_a1.find(-1);
	CPPUNIT_ASSERT(i == v_a1.end());
		

}

void UsesTest::TestGetProcedureUsesVariable(){

	// get procedures using x: 0, 1
	PROCINDEX_ARRAY v = u1.GetProcedureUsesVariable(0);
	auto i = v.find(0);

	CPPUNIT_ASSERT(i != v.end());

	i = v.find(1);
	CPPUNIT_ASSERT(i != v.end()); 

	// get procedures using y: 0
	v = u1.GetProcedureUsesVariable(1);
	i = v.find(0);
	CPPUNIT_ASSERT(i != v.end());

	i = v.find(1);
	CPPUNIT_ASSERT(i == v.end());

	// procedures using z: 0, 1
	v = u1.GetProcedureUsesVariable(2);
	i = v.find(0);
	CPPUNIT_ASSERT(i != v.end());

	i = v.find(1);
	CPPUNIT_ASSERT(i != v.end());

	// procedures using i: 0
	v = u1.GetProcedureUsesVariable(3);
	i = v.find(0);
	CPPUNIT_ASSERT(i != v.end());

	i = v.find(1);
	CPPUNIT_ASSERT(i == v.end());
}
	

void UsesTest::TestGetVariablesUsedByProcedure(){
	VARINDEX_ARRAY v_a1 = u1.GetVariablesUsedByProcedure(0);

	auto i = v_a1.find(0);
	CPPUNIT_ASSERT(i != v_a1.end());

	i = v_a1.find(1);
	CPPUNIT_ASSERT(i != v_a1.end());

	i = v_a1.find(2);
	CPPUNIT_ASSERT(i != v_a1.end());

	i = v_a1.find(3);
	CPPUNIT_ASSERT(i != v_a1.end());
	

}



void UsesTest::TestGetContainerUses() 
{
	STMT ifstmt;
	ifstmt.node_type = WHILE;
	ifstmt.statement_number = 2;

	CPPUNIT_ASSERT(u1.GetContainerUses(ifstmt, 0, WHILE));
	CPPUNIT_ASSERT(!u1.GetContainerUses(ifstmt, 1, WHILE));
	CPPUNIT_ASSERT(u1.GetContainerUses(ifstmt, 2, WHILE));
	CPPUNIT_ASSERT(u1.GetContainerUses(ifstmt, 3, WHILE));

}

void UsesTest::TestGetStatementUses() 
{
	STMT s1, s2, s4, s5;
	s1.statement_number = 1;
	s2.statement_number = 2;
	s4.statement_number = 4;
	s5.statement_number = 5;

	// s1 use x: true
	CPPUNIT_ASSERT(u1.GetStatementUses(s1, 0));
	// s1 use y: t
	CPPUNIT_ASSERT(u1.GetStatementUses(s1, 1));
	// s1 use z: t
	CPPUNIT_ASSERT(u1.GetStatementUses(s1, 2));
	CPPUNIT_ASSERT(!u1.GetStatementUses(s1, 3));

	// s2 use y:f
	CPPUNIT_ASSERT(!u1.GetStatementUses(s2, 1));
	// s2 use x:t
	CPPUNIT_ASSERT(u1.GetStatementUses(s2, 0));
	// s2 use i:t
	CPPUNIT_ASSERT(u1.GetStatementUses(s2, 3));
	// s2 use z: t
	CPPUNIT_ASSERT(u1.GetStatementUses(s2, 2));


	// s4 use x
	CPPUNIT_ASSERT(u1.GetStatementUses(s4, 0));
	// s4 use i:false
	CPPUNIT_ASSERT(!u1.GetStatementUses(s4, 3));
	// s4 use z: t
	CPPUNIT_ASSERT(u1.GetStatementUses(s4, 2));
	// s4 use y: false
	CPPUNIT_ASSERT(!u1.GetStatementUses(s4, 1));

	// s5 use x
	CPPUNIT_ASSERT(u1.GetStatementUses(s5, 0));
	// s5 use i:false
	CPPUNIT_ASSERT(!u1.GetStatementUses(s5, 3));
	// s5 use z: t
	CPPUNIT_ASSERT(u1.GetStatementUses(s5, 2));
	// s5 use y: false
	CPPUNIT_ASSERT(!u1.GetStatementUses(s5, 1));

}

void UsesTest::TestGetProcedureUses()
{

	CPPUNIT_ASSERT(u1.GetProcedureUses(0, 0));

	CPPUNIT_ASSERT(u1.GetProcedureUses(0, 1));
	
	CPPUNIT_ASSERT(u1.GetProcedureUses(0, 2));
	CPPUNIT_ASSERT(u1.GetProcedureUses(0, 3));

	CPPUNIT_ASSERT(u1.GetProcedureUses(1, 0));
	CPPUNIT_ASSERT(u1.GetProcedureUses(1, 2));
}

#endif